﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.ServiceModel;
using System.Windows;
using Omniscient.Foundation.ApplicationModel;
using Omniscient.Foundation.ApplicationModel.Security;
using Omniscient.Foundation.Contrib.Data.MySql;
using Omniscient.Foundation.Data;
using Omniscient.Foundation.Security;
using Omniscient.TimeTracker.BusinessModel;
using Omniscient.TimeTracker.BusinessModel.Commands;
using Omniscient.TimeTracker.BusinessModel.Security;
using Omniscient.TimeTracker.Data;
using Omniscient.TimeTracker.Data.Adapters.MySql;
using Omniscient.TimeTracker.Presentation.Commands;

namespace Omniscient.TimeTracker.Test
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            string endpointName;

            ApplicationManager.Current.ObjectContainer = new Omniscient.Foundation.ObjectContainer();

            //register commands
            ApplicationManager.Current.ObjectContainer.Register<ChangeTaskCategoryCommand>(new ChangeTaskCategoryUICommand());
            ApplicationManager.Current.ObjectContainer.Register<StartTaskCommand>(new StartTaskUICommand());
            ApplicationManager.Current.ObjectContainer.Register<StopTaskCommand>(new StopTaskUICommand());

            endpointName = "Omniscient.TimeTracker.Server.SecurityService";
            ChannelFactory<ISecurityService> securityFactory = new ChannelFactory<ISecurityService>(endpointName);
            ApplicationManager.Current.ObjectContainer.Register<ISecurityService>(securityFactory.CreateChannel());

            ApplicationManager.Current.StartApplication();

            //register data adapters
            IConnectivity connectivity;
            connectivity = ApplicationManager.Current.ServiceProvider.GetService<IConnectivity>();
            ApplicationManager.Current.ObjectContainer.Register(new ClientAdapter(connectivity));
            
            ICredentialService credentialService = ApplicationManager.Current.ServiceProvider.GetService<ICredentialService>();
            credentialService.EnsureUserIsAuthenticated();
            SecurePrincipal principal = credentialService.CurrentPrincipal;

            endpointName = "Omniscient.TimeTracker.Server.TimeEntryAdapterService";
            ChannelFactory<IEntityAdapter<TimeEntry>> factory = new ChannelFactory<IEntityAdapter<TimeEntry>>(endpointName);
            factory.Credentials.UserName.UserName = principal.Identity.Name;
            IntPtr ptr = Marshal.SecureStringToBSTR(principal.Identity.Password);
            factory.Credentials.UserName.Password = Marshal.PtrToStringBSTR(ptr);
            Marshal.ZeroFreeBSTR(ptr);
            ApplicationManager.Current.ObjectContainer.Register<IEntityAdapter<TimeEntry>>(factory.CreateChannel());

            //register other objects
            ITimeEntryManager tem;
            tem = new TimeEntryManager();
            ApplicationManager.Current.ObjectContainer.Register(tem);
            
            EntityList<Client> c;
            c = GetClients();
            ApplicationManager.Current.ObjectContainer.Register(c);

            EntityList<Category> categories;
            categories = GetCategories();
            ApplicationManager.Current.ObjectContainer.Register(categories);

        }

        protected override void OnLoadCompleted(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnLoadCompleted(e);
        }

        private EntityList<Client> GetClients()
        {
            //TODO: Put into IComposers
            IConnectivity connectivity = ApplicationManager.Current.ServiceProvider.GetService<IConnectivity>();

            TaskAdapter taskAdapter = new TaskAdapter(connectivity);
            EntityList<Task> taskList = taskAdapter.LoadAll();

            ProjectAdapter projectAdapter = new ProjectAdapter(connectivity);
            EntityList<Project> projectList = projectAdapter.LoadAll();

            ClientAdapter clientAdapter = new ClientAdapter(connectivity);
            EntityList<Client> clientList = clientAdapter.LoadAll();

            // Should be included in ClientComposer
            Dictionary<Guid, Client> clientDictionary = new Dictionary<Guid, Client>();
            foreach (Client c in clientList)
            {
                clientDictionary.Add(c.Id, c);
            }
           
            // Should be included in ProjectComposer
            Dictionary<Guid, Project> projectDictionary =
                new Dictionary<Guid, Project>();
            foreach (Project p in projectList)
            {
                projectDictionary.Add(p.Id, p);
            }

            // Should be included in ProjectComposer
            foreach (Task t in taskList)
            {
                Guid foreignKey = t.ParentProject.Id;

                if (projectDictionary.ContainsKey(foreignKey))
                {
                    t.ParentProject = projectDictionary[foreignKey];
                    projectDictionary[foreignKey].Tasks.Add(t);
                }
            }

            // Should be included in ClientComposer
            foreach (Project p in projectList)
            {
                Guid foreignKey = p.ParentClient.Id;

                if (clientDictionary.ContainsKey(foreignKey))
                {
                    p.ParentClient = clientDictionary[foreignKey];
                    clientDictionary[foreignKey].Projects.Add(p);
                }
            }

            // Should be included in ClientComposer
            EntityList<Client> result = new EntityList<Client>();
            foreach (Client client in clientDictionary.Values)
            {
                result.Add(client);
            }
            return result;
        }

        private EntityList<Category> GetCategories()
        {
            IConnectivity connectivity = ApplicationManager.Current.ServiceProvider.GetService<IConnectivity>();
            CategoryAdapter adapter = new CategoryAdapter(connectivity);
            return adapter.LoadAll();
        }
    }
}
